home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CODECS.ZIP / codecs / francais / codrle3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-13  |  9.4 KB  |  231 lines

  1. /* Fichier: codrle3.c
  2.    Auteur: David Bourgin
  3.    Date de creation: 1/2/94
  4.    Date de derniere mise a jour: 24/7/95
  5.    Dessein: Exemple de codage RLE type 3 avec comme donnees a compresser le contenu d'un fichier.
  6. */
  7.  
  8. #include <stdio.h>
  9. /* Pour les routines printf,fputc,fread,fwrite et rewind */
  10. #include <memory.h>
  11. /* Pour les routines memset,memcpy */
  12. #include <stdlib.h>
  13. /* Pour la routine exit */
  14.  
  15. /* Codes d'erreur renvoyes a l'appelant */
  16. #define NO_ERROR      0
  17. #define BAD_FILE_NAME 1
  18. #define BAD_ARGUMENT  2
  19.  
  20. /* Constantes pratiques */
  21. #define FALSE 0
  22. #define TRUE  1
  23.  
  24. #define TAILLE_TRAME_MAX  256
  25.  
  26. /* Variables globales */
  27. FILE *f_source,*f_dest;
  28.  
  29. unsigned int index=0,
  30.              taille_tmp_lec=0;
  31. unsigned char tmp_lec[3*256];
  32.  
  33. typedef struct { unsigned int taille_tab;
  34.                  unsigned char *val_tab;
  35.                } t_tab;
  36. #define TAILLE_TAB(tableau)  ((tableau).taille_tab)
  37. #define VAL_TAB(tableau)  ((tableau).val_tab)
  38. #define SONT_EGAUX(tableau1,tableau2)  ((TAILLE_TAB(tableau1)==TAILLE_TAB(tableau2))&&(!memcmp(VAL_TAB(tableau1),VAL_TAB(tableau2),TAILLE_TAB(tableau1))))
  39.  
  40. /* Pseudo procedures */
  41. #define taille_restante_a_lire()  (taille_tmp_lec-index)
  42. #define charger_bloc()  { if (!taille_restante_a_lire())\
  43.                              { taille_tmp_lec=fread(tmp_lec,1,sizeof(tmp_lec),f_source);\
  44.                                index=0;\
  45.                              }\
  46.                         }
  47. #define repositionner_index(i)  (index=(i))
  48. #define debut_des_donnees()  { (void)rewind(f_source); taille_tmp_lec=0; index=0; }
  49. #define fin_des_donnees()  (taille_restante_a_lire()?FALSE:(index=0,!(taille_tmp_lec=fread(tmp_lec,1,sizeof(tmp_lec),f_source))))
  50. #define lire_octet()  ((unsigned char)(fin_des_donnees()?EOF:tmp_lec[index++]))
  51. #define lire_tableau(tableau,nb_a_lire)  { TAILLE_TAB(tableau)=(nb_a_lire);\
  52.                                            VAL_TAB(tableau)= &(tmp_lec[index]);\
  53.                                            index += (nb_a_lire);\
  54.                                          }
  55. #define ecrire_octet(x)  ((void)fputc((unsigned char)(x),f_dest))
  56. #define ecrire_tableau(tableau)  ((void)fwrite(VAL_TAB(tableau),1,TAILLE_TAB(tableau),f_dest))
  57. #define completer_bloc()  { (void)memcpy(tmp_lec,&(tmp_lec[index]),taille_restante_a_lire());\
  58.                             taille_tmp_lec=fread(&(tmp_lec[taille_restante_a_lire()]),1,sizeof(tmp_lec)-taille_restante_a_lire(),f_source)+taille_restante_a_lire();\
  59.                             index=0;\
  60.                           }
  61.  
  62. void chercher_occurrle3(nb_trames,taille_trame,
  63.                         repetition_ok)
  64. /* Parametres en sortie: nb_trames, taille_trame et repetition_ok sont modifies
  65.    Action: Recherche dans le tampon d'octets une repetition de trame
  66.    dont la taille et la repetition seront respectivement dans taille_trame et nb_trames.
  67.    Si une repetition est rencontree, repetition_ok renvoie TRUE sinon repetition_ok renvoie FALSE
  68.    Erreurs: S'il n'y a pas de trames multiples alors nb_trames ne sera pas modifie
  69.    S'il y a repetition, telle que (nb_trames-1)*taille_trame>3, le tampon est complete
  70.    pour ne contenir qu'une occurrence de la trame au debut
  71.    (les repetitions ont ete videes par appel a 'completer_bloc').
  72. */
  73. unsigned int *nb_trames,*taille_trame;
  74. int *repetition_ok;
  75. { int egalite_des_tableaux;
  76.   t_tab tableau1,tableau2;
  77.  
  78.   *taille_trame=1;
  79.   *repetition_ok=FALSE;
  80.   while ((*taille_trame<=TAILLE_TRAME_MAX)&&(taille_restante_a_lire()>=(*taille_trame << 1))&&(!*repetition_ok))
  81.         { lire_tableau(tableau1,*taille_trame);
  82.           lire_tableau(tableau2,*taille_trame);
  83.           if (egalite_des_tableaux=SONT_EGAUX(tableau1,tableau2))
  84.              { *nb_trames=2;
  85.                while ((taille_restante_a_lire()>=*taille_trame)&&(*nb_trames<=255)&&(egalite_des_tableaux))
  86.                      { if ((*nb_trames-1)*(*taille_trame)>3)
  87.                           { if (*repetition_ok)
  88.                                repositionner_index(*taille_trame);
  89.                             else { *repetition_ok=TRUE;
  90.                                    repositionner_index((*nb_trames-1)*(*taille_trame));
  91.                                  }
  92.                             completer_bloc();
  93.                             repositionner_index(*taille_trame);
  94.                           }
  95.                        lire_tableau(tableau2,*taille_trame);
  96.                        if (egalite_des_tableaux=SONT_EGAUX(tableau1,tableau2))
  97.                           (*nb_trames)++;
  98.                      }
  99.                if ((*nb_trames-1)*(*taille_trame)>3)
  100.                   { if (*repetition_ok)
  101.                        { if (egalite_des_tableaux)
  102.                             { repositionner_index(*taille_trame);
  103.                               completer_bloc();
  104.                             }
  105.                        }
  106.                     else { *repetition_ok=TRUE;
  107.                            repositionner_index((*nb_trames-1)*(*taille_trame));
  108.                            completer_bloc();
  109.                          }
  110.                     (*taille_trame)--;
  111.                   }
  112.                              /* Specifier a l'appelant qu'il y a eu repetition */
  113.              }
  114.           (*taille_trame)++;
  115.           repositionner_index(0);
  116.         }
  117. }
  118.  
  119. void ecrire_non_reprle3(octet_repere,octet_non_repete)
  120. /* Parametres en sortie: Aucun
  121.    Action: Ecrit dans le flux de sortie de compression l'octet_non_repete
  122.    octet_repere fait office de marqueur comme defini par la methode RLE 2
  123.    Erreurs: Une erreur d'entree/sortie peut perturber le deroulement de l'algorithme
  124. */
  125. unsigned char octet_repere,octet_non_repete;
  126. { if (octet_non_repete==octet_repere)
  127.      { ecrire_octet(octet_repere);
  128.        ecrire_octet(0);
  129.        ecrire_octet(0);
  130.      }
  131.   else ecrire_octet(octet_non_repete);
  132. }
  133.  
  134. void ecrire_reprle3(octet_repere,trame,repetition)
  135. /* Parametres en sortie: Aucun
  136.    Action: Ecrit dans le flux de sortie de compression un nombre 'repetition' fois 'trame' de taille 'taille_trame'
  137.    octet_repere fait office de marqueur comme defini par la methode RLE 3
  138.    Erreurs: Une erreur d'entree/sortie peut perturber le deroulement de l'algorithme
  139. */
  140. unsigned char octet_repere;
  141. t_tab trame;
  142. unsigned int repetition;
  143. { ecrire_octet(octet_repere);
  144.   ecrire_octet(repetition-1);
  145.   ecrire_octet(TAILLE_TAB(trame)-1);
  146.   ecrire_tableau(trame);
  147. }
  148.  
  149.  
  150. void codagerle3()
  151. /* Parametres en sortie: Aucun
  152.    Action: Compresse suivant la methode RLE type 3 tous les octets lus par la fonction lire_octet
  153.    Erreurs: Une erreur d'entree/sortie peut perturber le deroulement de l'algorithme
  154. */
  155. { register unsigned int i;
  156.   unsigned long int table_occurrences[256];
  157.   unsigned char octet_repere;
  158.   t_tab trame;
  159.   unsigned int nb_trames,taille_trame;
  160.   int repetition_valide;
  161.  
  162.   if (!fin_des_donnees())    /* Y a-t-il au moins un octet a analyser? */
  163.      {                       /* Initialiser le nombre d'occurrences de tous les octets a 0 */
  164.        (void)memset((char *)table_occurrences,0,sizeof(table_occurrences));
  165.                              /* Ceci equivaut a remplir table_occurrences de 0.
  166.                                 C'est plus rapide que boucler 256 fois */
  167.                              /* Valider les occurrences de table_occurrences en fonction des donnees a compresser */
  168.        while (!fin_des_donnees())
  169.              { octet_repere=lire_octet();
  170.                table_occurrences[octet_repere]++;
  171.              }
  172.        octet_repere=0;
  173.        for (i=1;i<=255;i++)
  174.            if (table_occurrences[i]<table_occurrences[octet_repere])
  175.               octet_repere=i;
  176.        ecrire_octet(octet_repere);
  177.        debut_des_donnees();
  178.        charger_bloc();
  179.        while (taille_restante_a_lire())
  180.              { chercher_occurrle3(&nb_trames,&taille_trame,&repetition_valide);
  181.                if (repetition_valide)
  182.                              /* Il y a eu repetition? */
  183.                   { lire_tableau(trame,taille_trame);
  184.                     ecrire_reprle3(octet_repere,trame,nb_trames);
  185.                   }
  186.                else          /* Pas de repetition de motif */
  187.                     ecrire_non_reprle3(octet_repere,lire_octet());
  188.                completer_bloc();
  189.              }
  190.      }
  191. }
  192.  
  193. void aide()
  194. /* Parametres en sortie: Aucun
  195.    Action: Affiche l'aide du programme et termine son execution
  196.    Erreurs: Aucune
  197. */
  198. { printf("Cet utilitaire permet de compresser un fichier par la methode RLE type 3\n");
  199.   printf("telle qu'elle est exposee dans 'La Video et Les Imprimantes sur PC'\n");
  200.   printf("\nUsage: codrle3 source destination\n");
  201.   printf("source: Nom du fichier a compresser\n");
  202.   printf("destination: Nom du fichier compresse\n");
  203. }
  204.  
  205. int main(argc,argv)
  206. /* Parametres en sortie: Renvoie un code d'erreur (0=Aucune)
  207.    Action: Procedure principale
  208.    Erreurs: Detectee, traitee et un code d'erreur est renvoye si necessaire
  209. */
  210. int argc;
  211. char *argv[];
  212. { if (argc!=3)
  213.      { aide();
  214.        exit(BAD_ARGUMENT);
  215.      }
  216.   else if ((f_source=fopen(argv[1],"rb"))==NULL)
  217.           { aide();
  218.             exit(BAD_FILE_NAME);
  219.           }
  220.        else if ((f_dest=fopen(argv[2],"wb"))==NULL)
  221.                { aide();
  222.                  exit(BAD_FILE_NAME);
  223.                }
  224.             else { codagerle3();
  225.                    fclose(f_source);
  226.                    fclose(f_dest);
  227.                  }
  228.   printf("Execution de codrle3 achevee.\n");
  229.   return (NO_ERROR);
  230. }
  231.